package com.lleice.web.aspect;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.lleice.common.annotation.DataScope;
import com.lleice.common.constant.Constant;
import com.lleice.common.entity.req.CommonReq;
import com.lleice.common.enums.ExceptionEnum;
import com.lleice.common.exception.BusinessException;
import com.lleice.service.dto.DepartmentTreeParentDto;
import com.lleice.service.dto.sys.UserDto;
import com.lleice.service.service.sys.ISysDepartmentService;
import com.lleice.web.constant.ScanPackageConstant;
import com.lleice.web.utils.RequestHolder;

import cn.hutool.core.util.StrUtil;

/**
 * 数据权限切面
 * @author lizihao
 *
 */
@Component
@Aspect
@Order(9)
public class DataScopeAspect {
	@Autowired
	private ISysDepartmentService iSysDepartmentService;

	@Pointcut(ScanPackageConstant.DATA_SCOPE_POINTCUT)
    public void dataScope() {
    }

	@Before("dataScope()")
	public void getDataScope(JoinPoint pjp) throws Throwable {
		MethodSignature signature = (MethodSignature) pjp.getSignature();
		DataScope annotation = signature.getMethod().getAnnotation(DataScope.class);
		//部门别名
		String deptAlias = annotation.deptAlias();
		String userAlias = annotation.userAlias();
		//service的第一个查询参数
		CommonReq req = (CommonReq) pjp.getArgs()[0];
		//从requestHolder获取当前线程用户
		UserDto user = RequestHolder.getCurrentUser();
		//校验部门id的数据权限
		depDataSource(deptAlias, req, user);
		//校验用户id的数据权限
		userDataSource(userAlias, req, user);
	  }

	/**
	 * 校验用户id的数据权限
	 * @param userAlias 关联用户id的表别名
	 * @param req 查询的service的第一个参数
	 * @param user 用户
	 * @throws BusinessException
	 */
	private void userDataSource(String userAlias, CommonReq req, UserDto user) throws BusinessException {
		if(!StrUtil.isBlank(userAlias)) {
			if(null == user) {
				throw new BusinessException(ExceptionEnum.QXDL);
			}
			if(user.getDataScope().equals(Constant.DATA_SCOPE_SELF)) {
				//本人的数据
				StringBuilder builder = new StringBuilder();
				builder.append(userAlias).append(".user_id = ").append(user.getId());
				req.setSql(builder.toString());
			}
		}
	}

	/**
	 * 校验部门id的数据权限
	 * @param deptAlias 关联部门id的表别名
	 * @param req 查询的service的第一个参数
	 * @param user 用户
	 * @throws BusinessException
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 */
	private void depDataSource(String deptAlias, CommonReq req, UserDto user)
			throws Exception {
		if(!StrUtil.isBlank(deptAlias)) {
			if(null == user) {
				throw new BusinessException(ExceptionEnum.QXDL);
			}
			if(user.getDataScope().equals(Constant.DATA_SCOPE_ALL)) {
				//全部数据权限,不做限制
				req.setSql("1=1");
			}else if(user.getDataScope().equals(Constant.DATA_SCOPE_SELF_DEP)) {
				//部门数据
				if(user.getDepartmentList().size() == 0) {
					//如果没有绑定部门，则查询不到数据
					req.setSql("1 = 0");
				}else {
					StringBuilder builder = new StringBuilder();
					builder.append(deptAlias).append(".dep_id IN(").
					append(user.getDepartmentList().stream().map(i -> String.valueOf(i)).collect(Collectors.joining(","))).append(")");
					req.setSql(builder.toString());
				}
			}else if(user.getDataScope().equals(Constant.DATA_SCOPE_SELF_CHILD_DEP)) {
				//部门及以下数据
				if(user.getDepartmentList().size() == 0) {
					//如果没有绑定部门，则查询不到数据
					req.setSql("1 = 0");
				}else {
					List<DepartmentTreeParentDto> departmentList = iSysDepartmentService.getAllDepartmentWithUser(user.getId());
					List<String> departmentNodeList = new ArrayList<String>();
					getNodes(departmentNodeList, departmentList, false);
					StringBuilder builder = new StringBuilder();
					builder.append(deptAlias).append(".dep_id IN(").
					append(departmentNodeList.stream().collect(Collectors.joining(","))).append(")");
					req.setSql(builder.toString());
				}
				
			}
		}
	}

	
	/**
	 * 递归获取所有父子节点
	 * @param permissionList
	 * @param resourceList
	 */
	private void getNodes(List<String> departmentNodeList, List<DepartmentTreeParentDto> resourceList,Boolean isChild) {
		for(DepartmentTreeParentDto d : resourceList) {
			if(d.getIsShow().equals(1) && !isChild) {
				departmentNodeList.add(d.getId());
			}else if(isChild) {
				departmentNodeList.add(d.getId());
			}
			if(d.getChildren().size()!=0) {
				getNodes(departmentNodeList, d.getChildren(),d.getIsShow().equals(1)?true:false);
			}
		}
	}
}
